﻿using Application.Common.Interfaces;
using Ardalis.Specification.EntityFrameworkCore;
using Common.Attributes;
using Common.Enums;
using Domain.Entities.Identity;
using Domain.Services;
using Domain.ValueObjects;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;

namespace Application.Features.Menus.Commands.Update;

#nullable disable

/// <summary>
/// 同步接口
/// </summary>
[Description("同步接口")]
[GroupDescription("菜单管理")]
public class ExecuteSyncAPICommand : IRequest<bool>
{
}

/// <summary>
/// 处理程序
/// </summary>
public class ExecuteSyncAPICommandHandler : IRequestHandler<ExecuteSyncAPICommand, bool>
{
    private readonly IApplicationDbContext _context;
    private readonly MenuDomainService _menuDomainService;

    public ExecuteSyncAPICommandHandler(
        IApplicationDbContext context,
        MenuDomainService menuDomainService)
    {
        _context = context;
        _menuDomainService = menuDomainService;
    }

    /// <summary>
    /// 业务逻辑
    /// </summary>
    /// <param name="request">请求参数</param>
    /// <param name="cancellationToken">取消标记</param>
    /// <returns>返回处理结果</returns>
    public async Task<bool> Handle(ExecuteSyncAPICommand request, CancellationToken cancellationToken)
    {
        var webApiMenus = _menuDomainService.WebAPIEndpointCollectionForMenu();

        var existMenus = await _context.Menus.ToListAsync();
        var nonExistentMenus = new List<Menu>();
        var changeableMenus = new List<Menu>();
        if (!existMenus.Any())
        {
            nonExistentMenus = webApiMenus.ToList();
            await _context.Menus.AddRangeAsync(nonExistentMenus);
            return true;
        }

        foreach (var webApiMenu in webApiMenus)
        {
            var menu = existMenus.SingleOrDefault(x => x.Code == webApiMenu.Code);
            var isExist = menu != null;
            if (isExist)
            {
                menu.Name = webApiMenu.Name;
                menu.HttpMethods = webApiMenu.HttpMethods;
                menu.Meta = new Meta(menu.Meta, menu.Meta.Type, webApiMenu.Name);

                changeableMenus.Add(menu);
            }
            else
            {
                var isHasSameMenuName = existMenus.Any(x => x.Name == webApiMenu.Name && x.Meta.Type == MetaType.Menu);
                if (isHasSameMenuName) continue;

                nonExistentMenus.Add(webApiMenu);
            }
        }

        _context.Menus.UpdateRange(changeableMenus);
        await _context.Menus.AddRangeAsync(nonExistentMenus);

        return true;
    }
}